// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:build ignore 
// +build ignore 

package main

import "strings"

// /注意：
// -整数类型位于寄存器的低部分。上部是垃圾。
// /-布尔类型使用寄存器的低位字节。0=假，1=真。
// 高位字节是垃圾。
// /-*常量指令可能使用大于指令编码的常数。
// 在本例中，汇编程序扩展为多条指令，并使用tmp 
// 寄存器（R23）。

// 后缀对各种指令的位宽度进行编码。
// V（长）=64位
// WU（字）=32位无符号
// W（字）=32位
// H（半字）=16位
// HU=16位无符号
// B（字节）=8位
// BU 8位无符号
// F（浮点）=32位浮点

// 注意：regalloc中未使用的寄存器不包括在此列表中，
// 因此regmask保持在int64 
// 手动编码regmask时要小心。
var regNamesMIPS64 = []string{
	"R0", // 常数0 
	"R1",
	"R2",
	"R3",
	"R4",
	"R5",
	"R6",
	"R7",
	"R8",
	"R9",
	"R10",
	"R11",
	"R12",
	"R13",
	"R14",
	"R15",
	"R16",
	"R17",
	"R18",
	"R19",
	"R20",
	"R21",
	"R22",
	// R23=regalloc 
	"R24",
	"R25",
	// R26由内核
	// R27由内核
	// R28=regalloc 
	"SP",  // 又名R29 
	"g",   // 又名R30 
	"R31", // 又名REGLINK 

	"F0",
	"F1",
	"F2",
	"F3",
	"F4",
	"F5",
	"F6",
	"F7",
	"F8",
	"F9",
	"F10",
	"F11",
	"F12",
	"F13",
	"F14",
	"F15",
	"F16",
	"F17",
	"F18",
	"F19",
	"F20",
	"F21",
	"F22",
	"F23",
	"F24",
	"F25",
	"F26",
	"F27",
	"F28",
	"F29",
	"F30",
	"F31",

	"HI", // 乘法的高位

	// 如果添加寄存器，请在运行时更新asyncPreempt。

	// 伪寄存器
	"SB",
}

func init() {
	// 将reg名称映射到reg整数。
	if len(regNamesMIPS64) > 64 {
		panic("too many registers")
	}
	num := map[string]int{}
	for i, name := range regNamesMIPS64 {
		num[name] = i
	}
	buildReg := func(s string) regMask {
		m := regMask(0)
		for _, r := range strings.Split(s, " ") {
			if n, ok := num[r]; ok {
				m |= regMask(1) << uint(n)
				continue
			}
			panic("register " + r + " not found")
		}
		return m
	}

	// 通用单个寄存器掩码
	var (
		gp         = buildReg("R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R31")
		gpg        = gp | buildReg("g")
		gpsp       = gp | buildReg("SP")
		gpspg      = gpg | buildReg("SP")
		gpspsbg    = gpspg | buildReg("SB")
		fp         = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
		lo         = buildReg("LO")
		hi         = buildReg("HI")
		callerSave = gp | fp | lo | hi | buildReg("g") // 运行时。setg（以及任何称呼它的人）可能会击败g 
		r1         = buildReg("R1")
		r2         = buildReg("R2")
		r3         = buildReg("R3")
		r4         = buildReg("R4")
	)
	// Common regInfo 
	var (
		gp01     = regInfo{inputs: nil, outputs: []regMask{gp}}
		gp11     = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
		gp11sp   = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
		gp21     = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
		gp2hilo  = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{hi, lo}}
		gpload   = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
		gpstore  = regInfo{inputs: []regMask{gpspsbg, gpg}}
		gpstore0 = regInfo{inputs: []regMask{gpspsbg}}
		gpxchg   = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
		gpcas    = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
		fp01     = regInfo{inputs: nil, outputs: []regMask{fp}}
		fp11     = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
		// fp1flags=regInfo{inputs:[]regMask{fp}}
		// fpgp=regInfo{inputs:[]regMask{fp}，outputs:[]regMask{gp gp}
		fp21      = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
		fp2flags  = regInfo{inputs: []regMask{fp, fp}}
		fpload    = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
		fpstore   = regInfo{inputs: []regMask{gpspsbg, fp}}
		readflags = regInfo{inputs: nil, outputs: []regMask{gp}}
	)
	ops := []opData{
		// 二进制运算
		{name: "ADDV", argLength: 2, reg: gp21, asm: "ADDVU", commutative: true},                             // arg0+arg1 
		{name: "ADDVconst", argLength: 1, reg: gp11sp, asm: "ADDVU", aux: "Int64"},                           // arg0+auxInt。生长素是32位的，在其他常量中也是如此。
		{name: "SUBV", argLength: 2, reg: gp21, asm: "SUBVU"},                                                // arg0-arg1 
		{name: "SUBVconst", argLength: 1, reg: gp11, asm: "SUBVU", aux: "Int64"},                             // arg0-生长素
		{name: "MULV", argLength: 2, reg: gp2hilo, asm: "MULV", commutative: true, typ: "(Int64,Int64)"},     // arg0*arg1，有符号，结果hi，lo 
		{name: "MULVU", argLength: 2, reg: gp2hilo, asm: "MULVU", commutative: true, typ: "(UInt64,UInt64)"}, // arg0*arg1，无符号，结果hi，lo 

		{name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0+arg1-
		{name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0+arg1-
		{name: "SUBF", argLength: 2, reg: fp21, asm: "SUBF"},                    // arg0-arg1-
		{name: "SUBD", argLength: 2, reg: fp21, asm: "SUBD"},                    // arg0-arg1-
		{name: "MULF", argLength: 2, reg: fp21, asm: "MULF", commutative: true}, // arg0*arg1-
		{name: "MULD", argLength: 2, reg: fp21, asm: "MULD", commutative: true}, // arg0*arg1-

		{name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true},                  // arg0 | arg1 
		{name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true, typ: "UInt64"}, // arg0 ^ arg1 
		{name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64", typ: "UInt64"}, // arg0 ^ auxInt 
		{name: "NOR", argLength: 2, reg: gp21, asm: "NOR", commutative: true},                // ^（arg0 | arg1）
		{name: "NORconst", argLength: 1, reg: gp11, asm: "NOR", aux: "Int64"},                // ^（arg0 | auxInt）

		{name: "NEGV", argLength: 1, reg: gp11},                // /-arg0 

		// shift 
		{name: "SLLV", argLength: 2, reg: gp21, asm: "SLLV"},                    // arg0<<arg1，移位量为mod 64 
		{name: "SLLVconst", argLength: 1, reg: gp11, asm: "SLLV", aux: "Int64"}, // arg0<<auxInt 
		{name: "SRLV", argLength: 2, reg: gp21, asm: "SRLV"},                    // arg0>>arg1，unsigned，移位量为mod 64 

		// 比较
		{name: "SGT", argLength: 2, reg: gp21, asm: "SGT", typ: "Bool"},                      // 1如果arg0>arg1（有符号），0否则
		{name: "SGTconst", argLength: 1, reg: gp11, asm: "SGT", aux: "Int64", typ: "Bool"},   // 1如果auxInt>arg0（有符号），0否则
		{name: "SGTU", argLength: 2, reg: gp21, asm: "SGTU", typ: "Bool"},                    // 1如果arg0>arg1（无符号），0否则

		{name: "CMPGEF", argLength: 2, reg: fp2flags, asm: "CMPGEF", typ: "Flags"}, // flags=true如果arg0>=arg1，float32-
		{name: "CMPGED", argLength: 2, reg: fp2flags, asm: "CMPGED", typ: "Flags"}, // flags=true如果arg0>=arg1，float64-
		{name: "CMPGTF", argLength: 2, reg: fp2flags, asm: "CMPGTF", typ: "Flags"}, // flags=true如果arg0>arg1，float32-
		{name: "CMPGTD", argLength: 2, reg: fp2flags, asm: "CMPGTD", typ: "Flags"}, // flags=true如果arg0>arg1，float64-

		{name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint转换为64位浮点

		{name: "MOVVaddr", argLength: 1, reg: regInfo{inputs: []regMask{buildReg("SP") | buildReg("SB")}, outputs: []regMask{gp}}, aux: "SymOff", asm: "MOVV", rematerializeable: true, symEffect: "Addr"}, // arg0+auxint+aux。（*gc.Sym），arg0=SP/SB 

		{name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"},     // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+生长素+aux加载。arg1=mem。
		{name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16", faultOnNilArg0: true, symEffect: "Read"},    // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+生长素+辅助加载。arg1=mem。
		{name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "Int32", faultOnNilArg0: true, symEffect: "Read"},    // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVWUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVWU", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+生长素+辅助加载。arg1=mem。
		{name: "MOVVload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVV", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"},   // 从arg0+生长素+aux加载。arg1=mem。
		{name: "MOVFload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVF", typ: "Float32", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+auxInt+aux加载。arg1=mem。
		{name: "MOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVD", typ: "Float64", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+生长素+aux加载。arg1=mem。

		{name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将arg1的1字节存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将2字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将4字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVVstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将4字节的arg1存储到arg0+auxInt+aux。arg2=mem。
		{name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8字节的arg1存储到arg0+auxInt+aux。arg2=mem。

		{name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将0的1字节存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将0的2个字节存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将4字节的0存储到arg0+auxInt+aux。arg1=mem。
		{name: "MOVVstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将8字节的0存储到arg0+auxInt+aux。ar12=mem。

		// 转换
		{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVB"},   // 从arg0移动，从字节
		{name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // 从arg0移动，从字节
		{name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVH"},   // 从arg0移动，从半
		{name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // 从arg0移动，从半
		{name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"},   // 从arg0移动，从单词
		{name: "MOVWUreg", argLength: 1, reg: gp11, asm: "MOVWU"}, // 从arg0移动，unsign从单词
		{name: "MOVVreg", argLength: 1, reg: gp11, asm: "MOVV"},   // 扩展自arg0 

		{name: "MOVVnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // 否，在同一寄存器

		{name: "MOVWF", argLength: 1, reg: fp11, asm: "MOVWF"},     // int32->float32 
		{name: "MOVWD", argLength: 1, reg: fp11, asm: "MOVWD"},     // int32->float64 
		{name: "MOVVF", argLength: 1, reg: fp11, asm: "MOVVF"},     // int64->float32 
		{name: "MOVVD", argLength: 1, reg: fp11, asm: "MOVVD"},     // int64->float64 
		{name: "TRUNCFW", argLength: 1, reg: fp11, asm: "TRUNCFW"}, // float32->int32 
		{name: "TRUNCDW", argLength: 1, reg: fp11, asm: "TRUNCDW"}, // float64->int64 
		{name: "TRUNCFV", argLength: 1, reg: fp11, asm: "TRUNCFV"}, // 275

		// 函数调用
		{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                                               // 调用静态函数aux。（*obj.LSym）。arg0=mem，auxint=argsize，返回mem 
		{name: "CALLtail", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true, tailCall: true},                                 // tail call静态函数aux。（*obj.LSym）。arg0=mem，auxint=argsize，返回mem 
		{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R22"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // 通过闭包调用函数。arg0=codeptr，arg1=closure，arg2=mem，auxint=argsize，返回mem 
		{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                         // 通过指针调用fn。arg0=codeptr，arg1=mem，auxint=argsize，返回mem 

		// duffzero 
		// arg0=内存到零的地址
		// arg1=mem 
		// auxint=offset到duffzero代码中开始执行
		// 返回mem 
		// R1。REGRT1更改为副作用
		{
			name:      "DUFFZERO",
			aux:       "Int64",
			argLength: 2,
			reg: regInfo{
				inputs:   []regMask{gp},
				clobbers: buildReg("R1 R31"),
			},
			faultOnNilArg0: true,
		},

		// duffcopy 
		// arg0=dst内存地址（在R2中更改为副作用）
		// arg1=src内存地址（在R1中更改为副作用）
		// arg2=mem 
		// auxint=偏移到duffcopy代码中开始执行
		// 返回mem 
		{
			name:      "DUFFCOPY",
			aux:       "Int64",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R2"), buildReg("R1")},
				clobbers: buildReg("R1 R2 R31"),
			},
			faultOnNilArg0: true,
			faultOnNilArg1: true,
		},

		// 或未对齐的归零
		// arg0=内存地址为零（在R1中，更改为副作用）
		// arg1=最后一个元素的地址为零
		// arg2=mem 
		// auxint=alignment 
		// 返回mem 
		// SUBV$8，R1 
		// MOV R0，8（R1）
		// BNE Rarg1，R1，-2（PC）
		{
			name:      "LoweredZero",
			aux:       "Int64",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R1"), gp},
				clobbers: buildReg("R1"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
		},

		// 大或未对齐移动
		// arg0=dst内存地址（在R2中，更改为副作用）
		// arg3=内存
		// auxint=对齐
		// SUBV$8，R1 
		// MOV8（R1），Rtmp 
		// MOVV Rtmp，（R2）
		// ADDV$8，R1 
		{
			name:      "LoweredMove",
			aux:       "Int64",
			argLength: 4,
			reg: regInfo{
				inputs:   []regMask{buildReg("R2"), buildReg("R1"), gp},
				clobbers: buildReg("R1 R2"),
			},
			clobberFlags:   true,
			faultOnNilArg0: true,
			faultOnNilArg1: true,
		},

		// 从arg0加载。arg1=mem。
		// 返回<value，memory>，以便可以与其他加载一起正确排序。
		{name: "LoweredAtomicLoad8", argLength: 2, reg: gpload, faultOnNilArg0: true},
		{name: "LoweredAtomicLoad32", argLength: 2, reg: gpload, faultOnNilArg0: true},
		{name: "LoweredAtomicLoad64", argLength: 2, reg: gpload, faultOnNilArg0: true},

		// 原子商店。
		// 将arg1存储到arg0。arg2=mem。返回内存。
		{name: "LoweredAtomicStore8", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicStore32", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicStore64", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
		// 将零存储到arg0。arg1=mem。返回内存。
		{name: "LoweredAtomicStorezero32", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
		{name: "LoweredAtomicStorezero64", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},

		// 原子交换。
		// 将arg1存储到arg0。arg2=mem。返回<old content of*arg0，memory>。
		// 同步
		// LL（Rarg0），Rout 
		// MOVV Rarg1，Rtmp 
		// SC Rtmp，（Rarg0）
		// BEQ Rtmp，-3（PC）
		// 同步
		{name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子添加。
		// /*arg0+=arg1。arg2=mem。返回<新内容*arg0，内存>。
		// 同步
		// LL（Rarg0），Rout 
		// 添加Rarg1，Rout，Rtmp 
		// SC Rtmp，（Rarg0）
		// BEQ Rtmp，-3（PC）
		// 同步
		// 添加Rarg1，Rout 
		{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		// /*arg0+=生长素。arg1=mem。返回<新内容*arg0，内存>。生长素是32位的。
		{name: "LoweredAtomicAddconst32", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int32", resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicAddconst64", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int64", resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// 原子比较和交换。
		// arg0=指针，arg1=旧值，arg2=新值，arg3=内存。
		// if*arg0==arg1{
		// *arg0=arg2 
		// return（true，memory）
		// }else{
		// return（false，memory）
		// }
		// SYNC abcdefrarg 417
		// MOVV Rarg2，Rout 
		// SC Rout，（Rarg0）
		// BEQ Rout，-4（PC）
		// SYNC 
		{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},
		{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true},

		// pseudo ops 
		{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // arg0为零时惊慌。arg1=mem。

		{name: "FPFlagTrue", argLength: 1, reg: readflags},  // bool，如果FP标志为true，则为true，

		// 并将其排序到块的最开头，以防止其他
		// 使用R22（mips.REGCTXT，闭包指针）
		{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R22")}}, zeroWidth: true},

		// LoweredGetCallerSP返回当前函数调用方的SP。
		{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},

		// LoweredGetCallerPC计算其“调用者”将返回的PC。
		// 也就是说，如果f调用g“调用”GetCallerRPC，
		// 结果应该是g将返回的f内的PC。
		// 请参阅运行时/stubs。进行更详细的讨论。
		{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},

		// LoweredWB调用运行时。gcWriteBarrier。arg0=destptr，arg1=srcptr，arg2=mem，aux=runtime。gcWriteBarrier 
		// 如果需要，它会保存所有GP寄存器，
		// 但会删除R31（LR），因为它是一个调用
		// 和R23（REGTMP）。
		{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ gpg) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},

		// 其中有三个函数，因此它们可以有三个不同的寄存器输入。
		// 当我们检查0<=c<=cap（A），然后检查0<=b<=c（b），然后检查0<=A<=b（c）时，我们希望
		// 默认寄存器匹配，所以我们不需要不必要地复制寄存器。
		{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r3, r4}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicBounds）。
		{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicBounds）。
		{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见genericOps.go中的PanicBounds）。
	}

	blocks := []blockData{
		{name: "EQ", controls: 1},
		{name: "NE", controls: 1},
		{name: "LTZ", controls: 1}, // /<0 
		{name: "LEZ", controls: 1}, // /<=0 
		{name: "GTZ", controls: 1}, // />0 
		{name: "GEZ", controls: 1}, // />=0 
		{name: "FPT", controls: 1}, // /FP标志为真
		{name: "FPF", controls: 1}, // /FP标志为假
	}

	archs = append(archs, arch{
		name:            "MIPS64",
		pkg:             "cmd/internal/obj/mips",
		genfile:         "../../mips64/ssa.go",
		ops:             ops,
		blocks:          blocks,
		regnames:        regNamesMIPS64,
		gpregmask:       gp,
		fpregmask:       fp,
		specialregmask:  hi | lo,
		framepointerreg: -1, // 未使用
		linkreg:         int8(num["R31"]),
	})
}
